﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Utils
{
    public class AsyncLock
    {
        private readonly SemaphoreSlim semaphoreSlim;

        public AsyncLock(int initialCount)
        {
            semaphoreSlim = new SemaphoreSlim(initialCount, initialCount);
        }
        public AsyncLock(int initialCount, int maxCount)
        {
            semaphoreSlim = new SemaphoreSlim(initialCount, maxCount);
        }

        public async Task<IDisposable> Lock(int millisecondsTimeout = 5000, Func<Exception> errorFunc = null)
        {
            bool result = await semaphoreSlim.WaitAsync(millisecondsTimeout);
            if (!result)
            {
                //  int i = semaphoreSlim.Release();
                throw errorFunc?.Invoke() ?? Error.DefaultError("系统繁忙，请稍后再试");
            }
            return new Releaser(this);
        }


        struct Releaser : IDisposable
        {
            private readonly AsyncLock m_toRelease;

            public Releaser(AsyncLock toRelease)
            {
                m_toRelease = toRelease;
            }

            public void Dispose()
            {
                m_toRelease.semaphoreSlim.Release();
            }
        }
    }
}
